package com.mpdbailey.cleverdic.unittests;

import static org.junit.Assert.*;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

import junit.framework.Assert;

import org.junit.Test;

import com.mpdbailey.cleverdicandroid.DictionaryReader;
import com.mpdbailey.cleverdicandroid.R;
import com.mpdbailey.cleverdicandroid.WordList;
import com.mpdbailey.cleverdicandroid.WordListCallback;
import com.mpdbailey.unittests.diagnostics.Timing;

public class WordListTest
{
	private class TestWordListCallback implements WordListCallback
	{
		ArrayList<String> matches = new ArrayList<String>();
		public List<String> GetMatches() {return matches;}
		
		@Override
		public void Update(String result)
		{
			matches.add(result);
		}
	}

	List<String> CreateList()
	{
		ArrayList<String> list = new ArrayList<String>();
		list.add("spectrum");
		list.add("commodore");
		list.add("oric");
		list.add("dragon");
		list.add("nextstep");
		list.add("vale");
		list.add("evesham");
		list.add("vaio");
		list.add("acorn");
		list.add("electron");
		list.add("amiga");
		list.add("atari");
		list.add("micro");
		list.add("eight");
		list.add("pectrums");
		list.add("bit");
		list.add("murtpecs");
		list.add("sinclair");
		list.add("research");
		return list;
	}

	List<String> LoadList()
	{
		InputStream inputStream = null;
		List<String> list = null;
		try
		{
			inputStream = this.getClass().getResourceAsStream(
					"res/wordlist.txt");
			list = DictionaryReader.LoadDictionary(inputStream);
		} catch (IOException e)
		{
			e.printStackTrace();
			Assert.fail("Unexpected exception loading list");
		}

		finally
		{
			if (inputStream != null)
			{
				try
				{
					inputStream.close();
				} catch (IOException e)
				{
				}
			}
		}
		return list;
	}
	@Test
	public void FindWildcardWords()
	{
		TestWordListCallback callback = new TestWordListCallback();
		WordList target = new WordList();
		target.SetWordList(LoadList());
		Timing timing = new Timing();
		target.FindWildcardWords("t#and",callback);
		assertEquals(6, callback.GetMatches().size());
		timing.Show("Find Wildcards took");
	}
	
	@Test
	public void FindMultiwordAnagramsTest1()
	{
		TestWordListCallback callback = new TestWordListCallback();
		WordList target = new WordList();
		target.SetWordList(LoadList());
		Timing timing = new Timing();
		target.FindMultiwordAnagrams("manchester", "united", callback);
		assertEquals(25, callback.GetMatches().size());
		assertEquals("detachment insure",callback.GetMatches().get(0));
		assertEquals("unmastered ethnic",callback.GetMatches().get(24));
		timing.Show("Find Multi Anagrams took");
	}
	@Test
	public void FindPartialWordsTest1()
	{
		TestWordListCallback callback = new TestWordListCallback();
		WordList target = new WordList();
		target.SetWordList(CreateList());
		target.FindPartialWords("a....",callback);
		assertEquals(3,callback.GetMatches().size());
		assertEquals("acorn",callback.GetMatches().get(0));
		assertEquals("amiga",callback.GetMatches().get(1));
		assertEquals("atari",callback.GetMatches().get(2));
	}
	@Test
	public void FindAnagramsTest1()
	{
		TestWordListCallback callback = new TestWordListCallback();
		WordList target = new WordList();
		target.SetWordList(CreateList());
		target.FindAnagrams("trumspec",callback);
		assertEquals(3,callback.GetMatches().size());
		assertEquals("spectrum",callback.GetMatches().get(0));
		assertEquals("pectrums",callback.GetMatches().get(1));
		assertEquals("murtpecs",callback.GetMatches().get(2));
	}
	
	@Test
	public void GetMatchingWordsTest1()
	{
		WordList target = new WordList();
		target.SetWordList(CreateList());
		List<String> matches = target.GetMatchingWords(new char[]{'a', 'c','x'},5);
		assertEquals(1, matches.size());
		assertEquals("eight", matches.get(0));
	}
	@Test
	public void GetMatchingWordsTest2()
	{
		WordList target = new WordList();
		target.SetWordList(CreateList());
		List<String> matches = target.GetMatchingWords(new char[]{'g', 'h','b'},5);
		assertEquals(3, matches.size());
		assertEquals("acorn", matches.get(0));
		assertEquals("atari", matches.get(1));
		assertEquals("micro", matches.get(2));
	}
	@Test
	public void RunQueryTest1()
	{
		TestWordListCallback callback = new TestWordListCallback();
		WordList target = new WordList();
		target.SetWordList(CreateList());
		String query = target.ConvertQuery("CRAno");
		target.RunQuery(query,callback);
		assertTrue(callback.GetMatches().size() == 1);
		assertEquals("acorn",callback.GetMatches().get(0));
	}

	@Test
	public void RunQueryTest2()
	{
		TestWordListCallback callback = new TestWordListCallback();
		WordList target = new WordList();
		target.SetWordList(CreateList());
		String query = target.ConvertQuery("murTCeps");
		target.RunQuery(query,callback);
		assertTrue(callback.GetMatches().size() == 3);
		assertEquals("spectrum", callback.GetMatches().get(0));
		assertEquals("pectrums", callback.GetMatches().get(1));
	}

	@Test
	public void RunQueryTest3()
	{
		TestWordListCallback callback = new TestWordListCallback();
		WordList target = new WordList();
		target.SetWordList(CreateList());
		target.RunQuery("IBM",callback);
		assertTrue(callback.GetMatches().size() == 0);
	}

	@Test
	public void RunQueryTest4()
	{
		TestWordListCallback callback = new TestWordListCallback();
		WordList target = new WordList();
		target.SetWordList(CreateList());
		String query = target.ConvertQuery("sp?c????");
		target.RunQuery(query,callback);
		assertTrue(callback.GetMatches().size() == 1);
		assertEquals("spectrum", callback.GetMatches().get(0));
	}

	@Test
	public void RunQueryTest5()
	{
		TestWordListCallback callback = new TestWordListCallback();
		WordList target = new WordList();
		target.SetWordList(CreateList());
		String query = target.ConvertQuery("a??r?");
		target.RunQuery(query,callback);
		assertEquals(2, callback.GetMatches().size());
		assertEquals("acorn", callback.GetMatches().get(0));
		assertEquals("atari", callback.GetMatches().get(1));
	}

	@Test
	public void RunQueryTest6()
	{
		TestWordListCallback callback = new TestWordListCallback();
		WordList target = new WordList();
		target.SetWordList(CreateList());
		target.RunQuery("zx????",callback);
		assertTrue(callback.GetMatches().size() == 0);
	}
	@Test
	public void RunQueryTest7()
	{
		TestWordListCallback callback = new TestWordListCallback();
		WordList target = new WordList();
		target.SetWordList(CreateList());
		String query = target.ConvertQuery("sp3r2");
		target.RunQuery(query,callback);
		assertEquals(1, callback.GetMatches().size());
		assertEquals("spectrum", callback.GetMatches().get(0));
	}
	@Test
	public void RunQueryTest8()
	{
		TestWordListCallback callback = new TestWordListCallback();
		WordList target = new WordList();
		target.SetWordList(CreateList());
		target.RunQuery("#on",callback);
		assertTrue(callback.GetMatches().size() == 2);
		assertEquals("dragon", callback.GetMatches().get(0));
		assertEquals("electron", callback.GetMatches().get(1));
	}
	@Test
	public void RunQueryTest9()
	{
		TestWordListCallback callback = new TestWordListCallback();
		WordList target = new WordList();
		target.SetWordList(CreateList());
		target.RunQuery("#o.",callback);
		assertTrue(callback.GetMatches().size() == 2);
		assertEquals("dragon", callback.GetMatches().get(0));
		assertEquals("electron", callback.GetMatches().get(1));
	}
	@Test
	public void ConvertQueryTest1()
	{
		WordList target = new WordList();
		String query = target.ConvertQuery("sp3r2");
		assertEquals("sp...r..", query);
	}
	@Test
	public void ConvertQueryTest2()
	{
		//Max word length test
		WordList target = new WordList();
		String query = target.ConvertQuery("hello9999999999");
		assertEquals("hello.........................", query);
	}
	@Test
	public void ConvertQueryTest3()
	{
		//Max word length test
		WordList target = new WordList();
		String query = target.ConvertQuery("T#and");
		assertEquals("t#and", query);
	}

	@Test
	public void FindSubAnagramsTest1()
	{
		TestWordListCallback callback = new TestWordListCallback();
		List<String> list = LoadList();
		WordList target = new WordList();
		target.SetWordList(list);
		target.FindSubAnagrams("earths",callback);
		assertEquals(22, callback.GetMatches().size());

	}
	@Test
	public void FindSubAnagramsTest2()
	{
		TestWordListCallback callback = new TestWordListCallback();
		//Check that does not contain multiple items
		List<String> list = LoadList();
		WordList target = new WordList();
		target.SetWordList(list);
		target.FindSubAnagrams("galls",callback);
		assertEquals(4, callback.GetMatches().size());

	}
	@Test
	public void FindSubAnagramsTest3()
	{
		TestWordListCallback callback = new TestWordListCallback();
		List<String> list = LoadList();
		WordList target = new WordList();
		target.SetWordList(list);
		target.FindSubAnagrams("X",callback);
		assertEquals(0, callback.GetMatches().size());

	}
	@Test
	public void FindSubAnagramsTest4()
	{
		TestWordListCallback callback = new TestWordListCallback();
		List<String> list = LoadList();
		WordList target = new WordList();
		target.SetWordList(list);
		target.FindSubAnagrams("ab",callback);
//		for(String word : matches)
//		{
//			System.out.println(word);
//		}
		assertEquals(2, callback.GetMatches().size());

	}
	@Test
	public void FindSubAnagramsTest5()
	{
		TestWordListCallback callback = new TestWordListCallback();
		List<String> list = LoadList();
		WordList target = new WordList();
		target.SetWordList(list);
		String query = target.ConvertQuery("GaLLs");
		target.FindSubAnagrams(query,callback);
		assertEquals(4, callback.GetMatches().size());

	}

	
}
